/* eslint-disable */

// function qs_ccp(x, y) {
//     return { x, y };
// }

const MIN_MISTAKE = 1;
const LINE_MISTAKE = 0.01;

const cc_p = cc.v2;

function cc_pAdd(a,b){
    return cc_p(a.x + b.x,a.y + b.y);
}
function cc_pSub(a,b){
    return cc_p(a.x - b.x,a.y - b.y);
}
function cc_pLengthSQ(a){
    let _x = a.x;
    let _y = a.y;
    return _x * _x + _y * _y;
}
function cc_pDistanceSQ(a,b){
    let _x = b.x - a.x;
    let _y = b.y - a.y;
    return _x * _x + _y * _y;
}
function cc_pDistance(a,b){
    let _x = b.x - a.x;
    let _y = b.y - a.y;
    return Math.sqrt(_x * _x + _y * _y);
}
function cc_pAngleSigned(a,b){
    return a.signAngle(b);
}

function cc_rectContainsPoint(r,p){
    return r.contains(p);
}

function cc_convertToNodeSpaceAR(node,p){
    let pt = node.convertToNodeSpaceAR(p);
    pt.x -= node._anchorPoint.x * node._contentSize.width;
    pt.y -= node._anchorPoint.y * node._contentSize.height;
    return pt;
}

function cc_pointInPolygon(point, polygon){
    var inside = false;
    var x = point.x;
    var y = point.y;

    // use some raycasting to test hits
    // https://github.com/substack/point-in-polygon/blob/master/index.js
    var length = polygon.length;

    for ( var i = 0, j = length-1; i < length; j = i++ ) {
        var xi = polygon[i].x, yi = polygon[i].y,
            xj = polygon[j].x, yj = polygon[j].y,
            intersect = ((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);

        if ( intersect ) inside = !inside;
    }

    return inside;    
    // return cc.Intersection.pointInPolygon(pt, vers);
}

function point_at_line_foot(point, start, end, isSegment) {
    var dx = end.x - start.x;
    var dy = end.y - start.y;
    var d = dx * dx + dy * dy;
    var t = ((point.x - start.x) * dx + (point.y - start.y) * dy) / d;
    var p;

    if (!isSegment) {
        p = cc_p(start.x + t * dx, start.y + t * dy);
    } else {
        if (d) {
            if (t < 0) p = start;
            else if (t > 1) p = end;
            else p = cc_p(start.x + t * dx, start.y + t * dy);
        } else {
            p = start;
        }
    }
    return p;
}

function rotate_by_angle(v, pivot, angle) {
    var cosa = Math.cos(angle),
        sina = Math.sin(angle);
    return cc_p(
        v.x * cosa - v.y * sina + pivot.x,
        v.x * sina + v.y * cosa + pivot.y
    );
}

function cals_node_vertexs(node, vers) {
    const pivot = cc_p(0, 0);
    const offset = cc_p(node.x, node.y);
    // const angle = (-node.rotation * Math.PI) / 180;
    const angle = (-node.angle * Math.PI) / 180;
    const r = node.scaleX < 0 ? true : false;
    const scale = node.scaleY;
    let ret = [];
    for (let i = 0, l = vers.length; i < l; ++i) {
        let v = cc_p(vers[i]);
        if (r) {
            v.x = -v.x;
        }
        v.x *= scale;
        v.y *= scale;
        let pt = rotate_by_angle(v, pivot, angle);
        ret.push(cc_pAdd(pt, offset));
    }
    if (r) {
        // 如果翻转的话,调整端点顺序
        let rs = [];
        for (let j = ret.length - 1; j >= 0; --j) {
            rs.push(ret[j]);
        }
        return rs;
    }
    return ret;
}

function cals_xyrf_vertexs(xyrf, vers, scale) {
    const pivot = cc_p(0, 0);
    const offset = cc_p(xyrf.x, xyrf.y);
    const angle = (-xyrf.r * Math.PI) / 180;
    const r = xyrf.f ? true : false;
    scale = scale || 1;
    let ret = [];
    for (let i = 0, l = vers.length; i < l; ++i) {
        let v = cc_p(vers[i]);
        if (r) {
            v.x = -v.x;
        }
        v.x *= scale;
        v.y *= scale;
        let pt = rotate_by_angle(v, pivot, angle);
        ret.push(cc_pAdd(pt, offset));
    }
    if (r) {
        // 如果翻转的话,调整端点顺序
        let rs = [];
        for (let j = ret.length - 1; j >= 0; --j) {
            rs.push(ret[j]);
        }
        return rs;
    }
    return ret;
}

function vertexs_attach_polygon(vers, polygon, diffSQ) {
    var i, l, j, k;
    let diff = diffSQ;
    let off = null;
    for (j = 0, k = polygon.length; j < k; ++j) {
        let v = polygon[j];
        for (i = 0, l = vers.length; i < l; ++i) {
            let d = cc_pDistanceSQ(v, vers[i]);
            if (d < diff) {
                diff = d;
                off = cc_pSub(v, vers[i]);
                //console.log('vertexs_attach_polygon', v, vers[i], j, i, d);
            }
        }
    }
    return off;
}

function vertexs_attach_line(vers, polygon, diffSQ) {
    let lines = [];
    let pt = polygon[0];
    for (let i = polygon.length - 1; i >= 0; --i) {
        lines.push([pt, polygon[i]]);
        pt = polygon[i];
    }

    let cnt = lines.length;
    let diff = diffSQ;
    let off = null;
    for (let i = 0, l = vers.length; i < l; ++i) {
        pt = vers[i];
        for (let j = 0; j < cnt; ++j) {
            let line = lines[j];
            let plf = point_at_line_foot(pt, line[0], line[1], true);
            let d = cc_pDistanceSQ(plf, pt);
            if (d < diff) {
                diff = d;
                off = cc_pSub(plf, pt);
            }
        }
    }

    return off;
}

function vertexs_rotato_line(center, vers, polygon, diffAng, diffDis) {
    let lines = [];
    let pt = polygon[0];
    for (let i = polygon.length - 1; i >= 0; --i) {
        lines.push([pt, polygon[i]]);
        pt = polygon[i];
    }

    let plns = [];
    let cnt = lines.length;
    let vcn = vers.length;
    for (let i = 0; i < vcn; ++i) {
        pt = vers[i];
        for (let j = 0; j < cnt; ++j) {
            let line = lines[j];
            // 如果此点在线上
            let disab = cc_pDistance(pt, line[0]);
            let disac = cc_pDistance(pt, line[1]);
            let disbc = cc_pDistance(line[0], line[1]);
            if (disab < MIN_MISTAKE) {
                plns.push({ pid: i, lid: j });
                continue;
            }
            if (disac < MIN_MISTAKE) {
                plns.push({ pid: i, lid: j });
                continue;
            }
            let dis = disac + disab - disbc;
            if (Math.abs(dis) < LINE_MISTAKE) {
                plns.push({ pid: i, lid: j });
                continue;
            }
            // if (pointInLine(pt, line[0], line[1])) {
            //     plns.push({ pid: i, lid: j });
            //     continue;
            // }
        }
    }

    //console.log('vertexs_rotato_line', plns);

    let lcn = vcn - 1;
    for (let i = 0, l = plns.length; i < l; ++i) {
        let pln = plns[i];
        let line = lines[pln.lid];
        let crosspt = vers[pln.pid];
        //console.log('vertexs_rotato_line at', crosspt, line);
        let ca = pln.pid > 0 ? vers[pln.pid - 1] : vers[lcn];
        let cb = pln.pid < lcn ? vers[pln.pid + 1] : vers[0];
        let vac = cc_pSub(ca, crosspt);
        let vbc = cc_pSub(cb, crosspt);
        let lac = cc_pSub(line[0], line[1]);
        let lbc = cc_pSub(line[1], line[0]);

        let a1 = (cc_pAngleSigned(vac, lac) * 180) / Math.PI;
        let a2 = (cc_pAngleSigned(vac, lbc) * 180) / Math.PI;
        let a3 = (cc_pAngleSigned(vbc, lac) * 180) / Math.PI;
        let a4 = (cc_pAngleSigned(vbc, lbc) * 180) / Math.PI;

        let diff = diffAng;
        let ret = null;
        if (Math.abs(a1) < diff) {
            diff = Math.abs(a1);
            ret = a1;
        }
        if (Math.abs(a2) < diff) {
            diff = Math.abs(a2);
            ret = a2;
        }
        if (Math.abs(a3) < diff) {
            diff = Math.abs(a3);
            ret = a3;
        }
        if (Math.abs(a4) < diff) {
            diff = Math.abs(a4);
            ret = a4;
        }

        if (ret) {
            return { r: ret };
        }
    }

    return null;
}

export {
    rotate_by_angle,
    cals_node_vertexs,
    cals_xyrf_vertexs,
    vertexs_attach_polygon,
    vertexs_attach_line,
    vertexs_rotato_line,
    cc_p,
    cc_pAdd,cc_pSub,cc_pLengthSQ,cc_pDistance,cc_pDistanceSQ,cc_pAngleSigned,cc_rectContainsPoint,cc_pointInPolygon,cc_convertToNodeSpaceAR,
};

/*
        pAdd: 'p1.add(p2)',
        pSub: 'p1.sub(p2)',
        pLengthSQ: 'p.magSqr()',
        pDistanceSQ: 'p1.sub(p2).magSqr()',
        pLength: 'p.mag()',
        pDistance: 'p1.sub(p2).mag()',
        pAngleSigned: 'v1.signAngle(v2)',
        rectContainsPoint: 'rect.contains(vec2)',
*/